#nullable disable
using System.Net;
using System.Diagnostics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Authorization;
using Blogs.LazyFox.Models;
using Blogs.LazyFox.Data;


namespace Blogs.LazyFox.Controllers
{
    public class BlogController : Controller
    {
        private readonly BlogsContext _blogContext;
        private readonly ILogger<BlogController> _logger;
        private readonly UserManager<PersonModel> _userManager;

        public BlogController(ILogger<BlogController> logger, BlogsContext blogsContext, UserManager<PersonModel> userManager)
        {
            _logger = logger;
            _blogContext = blogsContext;
            _userManager = userManager;
        }

        public async Task<IActionResult> index(string searchString, string[] searchTags)
        {
            IQueryable<string> tagQuery = from t in _blogContext.Tags
                                          orderby t.Name
                                          select t.Name;

            IQueryable<BlogModel> blogs = from b in _blogContext.Blogs
                                          orderby b.CreateTime descending
                                          select b;

            if (!string.IsNullOrEmpty(searchString))
            {
                blogs = blogs.Where(s => s.Title!.Contains(searchString));
            }
            if (searchTags.Any())
            {
                blogs = blogs.Where(blog => blog.hasTag(searchTags));
            }

            return View(await blogs.ToListAsync());
        }

        public IActionResult Create()
        {
            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Create([Bind("Title,Introduction,Article")] BlogModel blog)
        {

            blog.CreateTime = DateTime.Now;
            blog.Author = _blogContext.Authors.Find(_userManager.GetUserId(HttpContext.User)) ?? _blogContext.Authors.Find(_userManager.GetUserId(HttpContext.User));
            _blogContext.Add(blog);
            await _blogContext.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }

        [Authorize]
        public async Task<IActionResult> Edit(long? bid)
        {
            if (bid == null)
            {
                return NotFound();
            }

            var blog = await _blogContext.Blogs.FirstOrDefaultAsync(m => m.Bid == bid);
            if (blog == null || blog.AuthorId != _userManager.GetUserId(HttpContext.User))
            {
                return NotFound();
            }
            return View(blog);
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Edit(long bid, [Bind("Bid,Title,Introduction,Article")] BlogModel blog)
        {
            if (bid != blog.Bid)
            {
                return NotFound();
            }

            try
            {
                var originalBlog = await _blogContext.Blogs.FirstOrDefaultAsync(m => m.Bid == bid);

                if (originalBlog.AuthorId != _userManager.GetUserId(HttpContext.User))
                {
                    return NotFound();
                }
                originalBlog.Title = blog.Title;
                originalBlog.Introduction = blog.Introduction;
                originalBlog.Article = blog.Article;
                _blogContext.Update(originalBlog);
                await _blogContext.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!BlogExit(blog.Bid))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }
            return RedirectToAction(nameof(Index));

            // return View(blog);
        }



        [HttpGet]
        [AllowAnonymous]
        public async Task<IActionResult> Read(long? bid)
        {
            if (bid == null)
            {
                return NotFound();
            }
            var blog = await _blogContext.Blogs.FirstOrDefaultAsync(m => m.Bid == bid);
            blog.Author = await _blogContext.Users.FindAsync(blog.AuthorId);
            var tags = from t in _blogContext.Tags
                        select t;
            blog.Tags = await tags.ToListAsync();
            if (blog == null)
            {
                return NotFound();
            }

            return View(blog);
        }

        public async Task<IActionResult> Delete(long? bid)
        {
            if (bid == null)
            {
                return NotFound();
            }

            var blog = await _blogContext.Blogs
                .FirstOrDefaultAsync(m => m.Bid == bid);
            if (blog == null || !isBlogAuthor(blog))
            {
                return NotFound();
            }

            return View(blog);
        }


        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Delete(long bid)
        {
            var movie = await _blogContext.Blogs.FindAsync(bid);
            _blogContext.Blogs.Remove(movie);
            await _blogContext.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }

        public async Task<IActionResult> Stick(long bid)
        {
            var blog = await _blogContext.Blogs.FindAsync(bid);
            if (blog == null)
            {
                return NotFound();
            }
            return View(new TagModel(){MarkedBlog = blog});
        }

        [ValidateAntiForgeryToken]
        [HttpPost]
        public async Task<IActionResult> Stick(long bid, TagModel tag)
        {
            var blog = await _blogContext.Blogs.FindAsync(bid);

            tag.CraeteTime = DateTime.Now;
            tag.MarkedBlog = blog;

            _blogContext.Add(tag);
            await _blogContext.SaveChangesAsync();
            return RedirectToAction(nameof(Read), new RouteValueDictionary { { nameof(BlogModel.Bid), bid } });
        }

        private bool BlogExit(long bid)
        {
            return _blogContext.Blogs.Any(e => e.Bid == bid);
        }

        private bool isBlogAuthor(BlogModel blog) => blog.AuthorId == _userManager.GetUserId(HttpContext.User);
    }
}